package httpclient

import (
	"bytes"
	"encoding/json"
	"net/http"
	urlPkg "net/url"
	"sync"
	"time"
)
// http 简单封装
type HttpClient struct {
	client *http.Client
}


func NewHttpClient () *HttpClient {
	hc := &HttpClient{
		client: http.DefaultClient,
	}
	hc.client.Timeout = time.Second * 10

	return  hc
}

var textBufferPool = sync.Pool{
	New: func() interface{} {
		return bytes.NewBuffer(make([]byte, 0, 4<<10)) // 4KB
	},
}

var mediaBufferPool = sync.Pool{
	New: func() interface{} {
		return bytes.NewBuffer(make([]byte, 0, 10<<20)) // 10MB
	},
}


//url 不能带query参数，(不能包含 ? & 之类的)
//purlObj, _ := url.Parse(murl) 后续考虑使用url先解析再处理
//requset 为 http请求中 body
//response 为 http 响应
func (hc * HttpClient) Do(method string, url string, request interface{}, response interface{}, opt... Option) (err error) {

	opts := newHttpOptions(opt...)

	//构建真正的url ， 增加query参数（如果存在）
	realUrl := url
	query := ""
	for k, v := range  opts.UrlParams {
		if 0 < len (query) {
			query = query + "&"+ k + "=" + v
		} else {
			query = k + "=" + v
		}
	}

	if 0 < len (query) {
		realUrl = realUrl + "?" + urlPkg.QueryEscape(query)
	}

	// 构建请求

	//body 处理
	var httpReq *http.Request
	var httpResp *http.Response
	var buffer *bytes.Buffer = nil
	if nil != request{

		buffer = textBufferPool.Get().(*bytes.Buffer)
		buffer.Reset()
		defer textBufferPool.Put(buffer)

		encoder := json.NewEncoder(buffer)
		encoder.SetEscapeHTML(false)
		if err = encoder.Encode(request); err != nil {
			return
		}
		//requestBodyBytes := buffer.Bytes()
		//log.Println(buffer)
		httpReq, err = http.NewRequest(method, realUrl, buffer)
	} else {
		httpReq, err = http.NewRequest(method, realUrl, nil)
	}


	//增加header
	for k, v := range opts.Headers{
		httpReq.Header.Add(k,v)
	}

	httpResp, err = hc.client.Do(httpReq)
	if err != nil {
		return
	}
	defer httpResp.Body.Close()

	// 处理 返回结果的body ，默认处理JSON
	if nil != response {
		err = json.NewDecoder(httpResp.Body).Decode(response)
	}

	return
}